package com.balabala;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.balabala.annotation.Permission;
import com.balabala.constant.TokenConstant;
import com.balabala.constant.UserConstant;
import com.balabala.exception.CustomerException;
import com.balabala.gym_enum.ExceptionEnum;

import com.balabala.gym_enum.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author 何涛
 * @Date: 2023/04/25/ 19:47
 * @description 权限控制的切面
 */
@Slf4j
@Aspect
@Configuration
@ConditionalOnClass({Aspect.class})
public class PermissionAspect {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    HttpServletRequest request;
    @Around("execution(* com.balabala..controller.admin..*Controller.*(..))")
    public Object permission(ProceedingJoinPoint joinPoint)
    {
        try {

            MethodSignature methodSignature= (MethodSignature) joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            Permission permission=method.getAnnotation(Permission.class);
            if(permission==null)
            {
                log.info("{}方法不需要权限鉴定，直接放行",method.getName());
                return joinPoint.proceed();
            }
            log.info("开始鉴权。。。。");
            String adminToken = request.getHeader("admin-token");
            // 判断是否为admin用户
            JWT jwtToken = JWTUtil.parseToken(adminToken);
            String username = (String) jwtToken.getPayload("username");
            if(UserConstant.ADMIN.equals(username)){
                log.info("admin用户直接放行！！！！！！");
                return joinPoint.proceed();
            }
            if(StringUtils.isEmpty(adminToken))
            {
                log.info("用户没有携带token");
                throw new CustomerException(ExceptionEnum.GENERALLY_FAIL);
            }
            String value= permission.value();
            //todo 从请求中获取token
            log.info("adminToken:{}",adminToken);
            //todo 根据token从redis中查询用户权限
            Set<String> permissions= (Set<String>) redisTemplate.boundValueOps(UserConstant.USER_PERMISSION+adminToken).get();
            if(permissions==null||permissions.isEmpty())
            {
                log.info("该用户没有任何权限。。。");
                throw new CustomerException(ExceptionEnum.GENERALLY_FAIL);
            }
            if(!permissions.contains(value))
            {
                log.info("这个用户没有任何权限");
                throw new CustomerException(ResultEnum.GENERALLY_FAIL);
            }
            log.info("鉴权成功。。。");
            log.info("重置用户权限失效时间{}小时", TokenConstant.CACHE_USER_EXPIRE/3600);
            redisTemplate.boundValueOps(UserConstant.USER_PERMISSION+adminToken).expire(TokenConstant.CACHE_USER_EXPIRE, TimeUnit.SECONDS);
            Object res = joinPoint.proceed();

            return res;

        }  catch (Throwable e) {
            throw new RuntimeException(e);
        }

    }
}
